﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2011-05-05
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


class IFAvatar;


class IFAnimation : public IFMemObject
{
protected:
    explicit IFAnimation()
    {}

public:
    // 获取当前打开的模型ID
    // .return 如果为eCD_ErrorModel表示没有打开
    virtual FIDMODEL GetModelID() = 0;
    // 更新动画
    // .ntime 当前时间
    virtual void Update(DWORD ntime) = 0;
    // 渲染动画
    // .alpha 整个动画文件的渲染透明度
    virtual void Render(float alpha = 1.0f) = 0;
    // 渲染动画
    // .valpha 每个子集的透明度，如果valpha数量为空则仅渲染特效，如果valpha数量为1则所有子集按此透明度
    // .efc_alpha 其它附加效果的透明度
    //virtual void Render(FV_FLOAT& valpha, float efc_alpha = 1.0f) = 0;
    // 设置动画的当前位置
    // .x,y,z 目的坐标
    virtual void SetPosition(float x, float y, float z) = 0;
    virtual void SetPosition(FVECTOR3& p) = 0;
    // 设置动画的旋转量
    // .x,y,z 各轴旋转量，一般只需要z轴即可
    virtual void SetRotate(float x, float y, float z) = 0;
    // 设置动画缩放
    // .scale 新的缩放值
    virtual void SetScale(float scale) = 0;
    // 测试动画是否是个动画（动画帧的数量不为1）
    virtual bool IsAnimate() = 0;
    // 测试动画是否有骨骼混合（不一定是动画）
    virtual bool HasBoneBlend() = 0;
    // 测试射线是否穿过动画模型（精确检测，有一定量的消耗）
    // .frame_id 测试指定帧的数据(0xffffffff表示检测当前帧)
    // .ray 检查射线
    // .pvhit 如果有碰撞，返回碰撞坐标点返，可填0（pvhit.data1表示碰撞子集索引,pvhit.data2无用）
    // .thr 碰撞类型
    // .frame_id 指定的帧ID，如果为eCD_FMD_ErrorAnimKey表示取当前动帧的播放帧位置
    // .return 返回是否碰撞成功
    virtual bool IntersectRay(FRAY& ray, FHITRESULT* pvhit = 0, EF_HIT_TYPE thr = eHT_Default, DWORD frame_id = eCD_FMD_ErrorAnimKey) = 0;
    // 测试射线是否穿过动画模型（仅AABB检测）
    virtual bool IntersectAABB(FRAY& ray) = 0;
    // 获取模型的世界矩阵
    virtual const FMATRIX* const GetWorldMatrix() = 0;
    // 获取动画的骨骼矩阵列表地址，注意是偏移矩阵，用的时候需要乘上首矩阵
    virtual const FMATRIX* const GetBoneMatrixVec() = 0;
    // 获取动画的当前帧ID
    virtual DWORD GetFrameID() = 0;
    // 设置当前帧ID
    virtual void SetFrameID(DWORD id) = 0;
    // 获取模型数据信息
    virtual IFModelFile* GetModelData() = 0;
    // 播放动作
    // .name 在模型配置列表中的动作名，如果填0表示播放全部帧
    virtual void Play(EF_ANIMATE_MODE mode, const WCHAR* name = 0) = 0;
    virtual void Play(EF_ANIMATE_MODE mode, const ACHAR* name) = 0;
    // 播放动作
    // .start_id 起点帧ID
    // .end_id 结束帧ID
    // .one_loop 一次循环用时，毫秒，0表示默认速度
    virtual void Play(EF_ANIMATE_MODE mode, DWORD start_id, DWORD end_id, DWORD one_loop = 0) = 0;
    // 切换皮肤
    // .name 在模型配置列表中的皮肤，如果填0表示还原默认皮肤
    virtual void ModifySkin(const WCHAR* name = 0) = 0;
    virtual void ModifySkin(const ACHAR* name) = 0;
    // 取得当前绑定的时装信息
    virtual IFAvatar* GetAvatar() = 0;
    // 渲染骨架信息
    virtual void DrawSkeleton(DWORD color = 0xFFC010C0) = 0;
    // 获取整个模型的AABB，从第一帧的AABB模精计算出来的模拟AABB
    virtual const FAABB* const GetAABB() = 0;
    // 设置模型的AABB（一旦设置此值后，动画将不再自动更新AABB，包括旋转、平移等变化，均需要手动设置设置新的AABB）
    // .aabb 新的AABB值，如果为0表示恢复默认，且变为自动更新AABB
    virtual void SetAABB(FAABB* aabb) = 0;
    // 计算指定帧的AABB，是精确的AABB（有消耗，且忽略模型动画自身的可见状态，但子集的可见状态会影响AABB结果）
    // .frame_id 指定的帧ID，如果为eCD_FMD_ErrorAnimKey表示取当前动帧的播放帧位置
    virtual void BuildAABB(FAABB& aabb, DWORD frame_id = eCD_FMD_ErrorAnimKey) = 0;
    // 设置可见状态
    virtual void SetVisible(bool v) = 0;
    // 获取可见状态
    virtual bool GetVisible() = 0;
    // 设置某个子集的可见状态
    virtual void SetVisible(size_t sub_idx, bool vl) = 0;
    // 获取某个子集的可见状态
    virtual bool GetVisible(size_t sub_idx) = 0;
};